﻿#region License
// (c) Garry McGlennon 2009
// 
// This project is made available under the Microsoft Public License (Ms-PL)
// Code is provided as is and with no warrenty – Use at your own risk
// 
// View the project and the latest code at http://dnpframework.codeplex.com/
// 
// All other rights reserved.
// 
// blog: www.dotNetProfessional.com/blog/
#endregion
using System;


namespace dnp.Framework.Web
{
    /// <summary>
    /// This class provides thread wide timezone conversions.
    /// Once the local zone and server zone have been set they
    /// persist for the life of the 'logical' thread. 
    /// </summary>
    public static class TimeZoneEx
    {
        public static void SetClientTimeZone(string timeZoneId)
        {
            TimeZoneInfo tz;
            if (string.IsNullOrEmpty(timeZoneId))
                tz = TimeZoneInfo.Local;
            else
                tz = TimeZoneInfo.FindSystemTimeZoneById(timeZoneId);

            SafeLocalStorage.StoreItem("ClientTime", tz);
        }

        /// <summary>
        /// Returns the current timezone defined for the client. By default the timezone will be the local zone of the application.
        /// </summary>
        public static TimeZoneInfo ClientTimeZone
        {
            get
            {
                TimeZoneInfo tz = SafeLocalStorage.RetrieveItem<TimeZoneInfo>("ClientTime");
                if (tz == null)
                    tz = TimeZoneInfo.Local;

                return tz;
            }
        }

        /// <summary>
        /// Converts a date that is currently in the timezone of the client into the equivilant of that of the server
        /// </summary>
        /// <param name="date">date to convert</param>
        /// <returns></returns>
        public static DateTime ConvertClientToUtcTime(DateTime date)
        {
            if (date.Kind != DateTimeKind.Unspecified)
                date = new DateTime(date.Ticks, DateTimeKind.Unspecified);

            return TimeZoneInfo.ConvertTimeToUtc(date, ClientTimeZone);
        }

        /// <summary>
        /// Converts a date that is currently in the timezone of the server into the equivilant of that of the client
        /// </summary>
        /// <param name="date">date to convert</param>
        /// <returns></returns>
        public static DateTime ConvertUtcToClientTime(DateTime date)
        {
            if (date.Kind != DateTimeKind.Unspecified)
                date = new DateTime(date.Ticks, DateTimeKind.Unspecified);

            return TimeZoneInfo.ConvertTimeFromUtc(date, ClientTimeZone);
        }

        /// <summary>
        /// Extension method: Converts a date that is currently in the timezone of the server into the equivilant of that of the client
        /// </summary>
        public static DateTime ToClientTime(this DateTime source)
        {
            return ConvertUtcToClientTime(source);
        }

        /// <summary>
        /// Extension method: Converts a date that is currently in the timezone of the server into the equivilant of that of the client
        /// </summary>
        public static DateTime? ToClientTime(this DateTime? source)
        {
            if (source.HasValue)
                return ConvertUtcToClientTime(source.Value);
            else
                return source;
        }

        /// <summary>
        /// Extension method: Converts a date that is currently in the timezone of the client into the equivilant of that of the server
        /// </summary>
        public static DateTime ToUtcTime(this DateTime source)
        {
            return ConvertClientToUtcTime(source);
        }

        /// <summary>
        /// Extension method: Converts a date that is currently in the timezone of the client into the equivilant of that of the server
        /// </summary>
        public static DateTime? ToUtcTime(this DateTime? source)
        {
            if (source.HasValue)
                return ConvertClientToUtcTime(source.Value);
            else
                return source;
        }
    }
}
